/*
 *    This file is part of SSHTunneler.
 *
 *    Copyright 2009 Jean-Sebastien Gelinas <calestar@gmail.com>
 *
 *    SSHTunneler is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    SSHTunneler is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with SSHTunneler.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package sshtunneler.packager.gui.frames;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import sshtunneler.library.Server;
import sshtunneler.packager.data.PackagerServerContainer;
import sshtunneler.server_tunnel.gui.AddServer;
import sshtunneler.server_tunnel.gui.AddTunnel;
import sshtunneler.server_tunnel.tree.GenericServerTunnelTree;
import sshtunneler.server_tunnel.tree.MyServerTunnelTreeNode;
import sshtunneler.server_tunnel.tree.ServerTunnelRootNode;

public class ManageServersTunnels extends MyInternalFrame implements
		MouseListener {
	private static final long serialVersionUID = 1090190690221695122L;
	private JScrollPane jScrollPane1;
	private JTree jTree1;
	private ServerTunnelTree root;

	public ManageServersTunnels(MyInternalFrameActionDispatcherFrame dispatcher) {
		super(dispatcher);

		this.setClosable(true);
		this.setIconifiable(true);
		this.setResizable(true);
		this.setTitle("Manage Servers/Tunnels");
		this
				.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
		this.setPreferredSize(new java.awt.Dimension(400, 300));

		this.root = new ServerTunnelTree(this);
		this.jScrollPane1 = new javax.swing.JScrollPane();
		this.jTree1 = new javax.swing.JTree(this.root.root);

		this.jTree1.addMouseListener(this);
		this.jTree1.getSelectionModel().setSelectionMode(
				TreeSelectionModel.SINGLE_TREE_SELECTION);
		this.jScrollPane1.setName("jScrollPane1");
		this.jTree1.setName("jTree1");
		this.jTree1.setPreferredSize(new java.awt.Dimension(200, 64));
		this.jScrollPane1.setViewportView(this.jTree1);

		this.jTree1
				.addTreeWillExpandListener(new javax.swing.event.TreeWillExpandListener() {
					public void treeWillCollapse(
							javax.swing.event.TreeExpansionEvent evt)
							throws javax.swing.tree.ExpandVetoException {
					}

					public void treeWillExpand(
							javax.swing.event.TreeExpansionEvent evt)
							throws javax.swing.tree.ExpandVetoException {
						ManageServersTunnels.this.jTree1TreeWillExpand(evt);
					}
				});

		this.getContentPane().add(this.jScrollPane1,
				java.awt.BorderLayout.CENTER);
		this.pack();
	}

	public void refresh() {
		// Should not need to refresh: not listening to any events
	}

	private void jTree1TreeWillExpand(javax.swing.event.TreeExpansionEvent evt)
			throws javax.swing.tree.ExpandVetoException {
		TreePath selPath = evt.getPath();
		Object selection = selPath.getLastPathComponent();

		if (selection == null || !(selection instanceof MyServerTunnelTreeNode)) {
			return;
		}
		this.refreshNode((MyServerTunnelTreeNode) selection);
	}

	public void refreshNode(MyServerTunnelTreeNode selectedNode) {
		selectedNode.refresh();
		((DefaultTreeModel) this.jTree1.getModel()).reload(selectedNode);
	}

	public MyServerTunnelTreeNode getSelectedNode(MouseEvent e) {
		TreePath selPath = this.jTree1.getPathForLocation(e.getX(), e.getY());
		if (selPath == null) {
			return null;
		}
		this.jTree1.setSelectionPath(selPath);
		Object selection = this.jTree1.getLastSelectedPathComponent();

		if (selection == null) {
			return null;
		}
		if (!(selection instanceof MyServerTunnelTreeNode)) {
			return null;
		}

		return (MyServerTunnelTreeNode) selection;
	}

	public void mousePressed(MouseEvent e) {
		if (e.isPopupTrigger()) {
			MyServerTunnelTreeNode selection = this.getSelectedNode(e);
			if (selection == null) {
				return;
			}
			JPopupMenu popup = selection.getPopup();
			popup.show((Component) e.getSource(), e.getX(), e.getY());
		}
	}

	public void mouseReleased(MouseEvent e) {
		if (e.isPopupTrigger()) {
			MyServerTunnelTreeNode selection = this.getSelectedNode(e);
			if (selection == null) {
				return;
			}
			JPopupMenu popup = selection.getPopup();
			popup.show((Component) e.getSource(), e.getX(), e.getY());
		}
	}

	public void mouseClicked(MouseEvent e) {
	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	class ServerTunnelTree extends GenericServerTunnelTree implements
			ActionListener {
		/** Server menu **/
		private JMenuItem server_menu_edit;
		private JMenuItem server_menu_add_tunnel;
		private JMenuItem server_menu_remove;

		/** Tunnel menu **/
		private JMenuItem tunnel_menu_edit;
		private JMenuItem tunnel_menu_remove;

		/** Root menu **/
		private JMenuItem root_menu_add_server;

		/** Real Tree **/
		private ServerTunnelRootNode root;
		private ManageServersTunnels parent;

		public ServerTunnelTree(ManageServersTunnels p) {
			this.root = new ServerTunnelRootNode(this,
					PackagerServerContainer.inst);
			this.parent = p;

			this.server_menu_add_tunnel = new JMenuItem("Add tunnel");
			this.server_menu_remove = new JMenuItem("Remove this server");
			this.server_menu_edit = new JMenuItem("Edit");
			this.tunnel_menu_remove = new JMenuItem("Remove");
			this.tunnel_menu_edit = new JMenuItem("Edit");
			this.root_menu_add_server = new JMenuItem("Add server");

			this.tunnel_menu_remove.addActionListener(this);
			this.tunnel_menu_edit.addActionListener(this);
			this.server_menu_add_tunnel.addActionListener(this);
			this.server_menu_remove.addActionListener(this);
			this.server_menu_edit.addActionListener(this);
			this.root_menu_add_server.addActionListener(this);
		}

		@Override
		public JPopupMenu get_root_menu() {
			JPopupMenu popup = new JPopupMenu();

			popup.add(this.root_menu_add_server);

			return popup;
		}

		@Override
		public JPopupMenu get_server_menu() {
			JPopupMenu popup = new JPopupMenu();

			popup.add(this.server_menu_add_tunnel);
			popup.addSeparator();
			popup.add(this.server_menu_edit);
			popup.addSeparator();
			popup.add(this.server_menu_remove);

			return popup;
		}

		@Override
		public JPopupMenu get_tunnel_menu() {
			JPopupMenu popup = new JPopupMenu();

			popup.add(this.tunnel_menu_edit);
			popup.addSeparator();
			popup.add(this.tunnel_menu_remove);

			return popup;
		}

		public void actionPerformed(ActionEvent e) {
			if (e.getSource().equals(this.server_menu_add_tunnel)) {
				AddTunnel gui = new AddTunnel(this.parent.dispatcher, this
						.getSelected_server(), null, this);
				gui.setLocationRelativeTo(this.parent.dispatcher);
				gui.setVisible(true);
				this.parent.refreshNode(this.getSelected_node());
			} else if (e.getSource().equals(this.server_menu_remove)) {
				this.getSelected_node().removeFromParent();
				PackagerServerContainer.inst.removeServer(this
						.getSelected_server());
			} else if (e.getSource().equals(this.server_menu_edit)) {
				AddServer gui = new AddServer(this.parent.dispatcher, this
						.getSelected_server(), this);
				gui.setLocationRelativeTo(this.parent);
				gui.setVisible(true);

				this.parent.refreshNode(this.getSelected_node());
			} else if (e.getSource().equals(this.root_menu_add_server)) {
				AddServer gui = new AddServer(this.parent.dispatcher, null,
						this);
				gui.setLocationRelativeTo(this.parent.dispatcher);
				gui.setVisible(true);

				this.parent.refreshNode(this.getSelected_node());
			} else if (e.getSource().equals(this.tunnel_menu_remove)) {
				this.getSelected_node().removeFromParent();
				this.getSelected_server().removeTunnel(
						this.getSelected_tunnel());
			} else if (e.getSource().equals(this.tunnel_menu_edit)) {
				AddTunnel gui = new AddTunnel(this.parent.dispatcher, this
						.getSelected_server(), this.getSelected_tunnel(), this);
				gui.setLocationRelativeTo(this.parent.dispatcher);
				gui.setVisible(true);
				this.parent.refreshNode(this.getSelected_node());
			}
		}

		public ServerTunnelRootNode getRoot() {
			return this.root;
		}

		@Override
		public Server create_server(String username, String hostname, int port) {
			Server newServer = new Server(username, hostname, port);

			PackagerServerContainer.inst.addServer(newServer);

			return newServer;
		}

		@Override
		public void process_server_action(boolean added, boolean deleted,
				boolean modified) {
			// Nothing
		}

		@Override
		public void process_tunnel_action(boolean added, boolean deleted,
				boolean modified) {
			// Nothing
		}
	}
}
